package com.hust.utils;

import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZOutputFile;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Utils {
    public static void deleteFolder(File folder) {
        if (folder.isDirectory()) {
            File[] files = folder.listFiles();
            if (files != null) {
                for (File file : files) {
                    file.delete();
                }
            }
        }
        folder.delete();
    }

    public static boolean writeCsv(String fileName, List<String> data) {
        //根据startIdx和endIdx生成excel文件，放入folder中
        //定义文件名格式并创建
        Path path = Paths.get(fileName);
        // 使用newBufferedWriter创建文件并写文件
        // 这里使用了try-with-resources方法来关闭流，不用手动关闭
        try (BufferedWriter writer =
                     Files.newBufferedWriter(path, StandardCharsets.US_ASCII)) {
            for (String line : data) {
                writer.write(line);
                writer.newLine();
            }
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    public static List<String> readCsv(String filename) {
        List<String> lines = new ArrayList<>();
        try {
            FileReader fileReader = new FileReader(filename);
            BufferedReader bufferedReader = new BufferedReader(fileReader);
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                lines.add(line);
            }
            bufferedReader.close();
            return lines;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String fullPath(String filename) {
        File file = new File(filename);
        if (!file.exists()) {
            String jarPath = System.getProperty("java.class.path");
            String jarDirectory = new File(jarPath).getParent();
            filename = jarDirectory + File.separator + filename;
            return filename;
        }
        else return file.getAbsolutePath();
    }

    public static String[] getFiles(File folder, String ext) {
        String[] files = folder.list((dir, name) -> name.toLowerCase().endsWith(ext.toLowerCase()));
        for (int i = 0; i < files.length; i++) {
            files[i] = folder.getPath() + File.separator + files[i];
        }
        return files;
    }

    public static String zipFile(File folder) {
        long start = System.currentTimeMillis();
        String[] files = getFiles(folder, ".csv");
        String filename = folder.getPath() + ".zip";
        try {
            ZipOutputStream zipFile = new ZipOutputStream(new FileOutputStream(filename));
            for (String file : files) {
                FileInputStream fis = null;
                try {
                    File csv = new File(file);
                    ZipEntry entry = new ZipEntry(csv.getName());
                    zipFile.putNextEntry(entry);
                    fis = new FileInputStream(file);
                    byte[] buffer = new byte[1024 * 200];
                    int count;
                    while ((count = fis.read(buffer)) > 0) {
                        zipFile.write(buffer, 0, count);
                    }
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                    e.printStackTrace();
                    return null;
                } finally {
                    zipFile.closeEntry();
                    fis.close();
                }
            }
            zipFile.close();
            long elapse = System.currentTimeMillis() - start;
            System.out.println(String.format("Zip files completed. It takes %d ms.", elapse));
            return filename;
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
            return null;
        }
    }

    public static String zipFile7z(File folder) {
        long start = System.currentTimeMillis();
        String[] files = getFiles(folder, ".csv");
        String filename = folder.getPath() + ".7z";
        try {
            SevenZOutputFile file7z = new SevenZOutputFile(new File(filename));
            for (String file : files) {
                FileInputStream fis = null;
                try {
                    File csv = new File(file);
                    SevenZArchiveEntry entry = file7z.createArchiveEntry(csv, csv.getName());
                    file7z.putArchiveEntry(entry);
                    fis = new FileInputStream(file);
                    byte[] buffer = new byte[1024 * 200];
                    int count;
                    while ((count = fis.read(buffer)) > 0) {
                        file7z.write(buffer, 0, count);
                    }
                } catch (IOException e) {
                    System.out.println(e.getMessage());
                    e.printStackTrace();
                    return null;
                } finally {
                    file7z.closeArchiveEntry();
                    fis.close();
                }
            }
            file7z.close();
            long elapse = System.currentTimeMillis() - start;
            System.out.println(String.format("Zip files completed. It takes %d ms.", elapse));
            return filename;
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(e.getMessage());
            return null;
        }
    }

    public static <T> List<T> deepCopy(List<T> src) {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        try {
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(src);
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            List<T> dest = (List<T>) in.readObject();
            return dest;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }
}
